#include<iostream>
#include<pthread.h>
#include<queue>
using namespace std;

const int default_thread = 5;

template<class T>
class ThreadPool
{
public:
  ThreadPool(int num = default_thread) :thread_num(num)
  {
    pthread_mutex_init(&mtx,nullptr);
    pthread_cond_init(&c_cond,nullptr);
    InitThreadPool();
  }
  ~ThreadPool()
  {
    pthread_mutex_destroy(&mtx);
    pthread_cond_destroy(&c_cond);  
  }
  void Lock()
  {
    pthread_mutex_lock(&mtx);
  }
  void UnLock()
  {
    pthread_mutex_unlock(&mtx);
  }
  void ComWait()
  {
    pthread_cond_wait(&c_cond,&mtx);
  }
  void ComWakeUp()
  {
    pthread_cond_signal(&c_cond);
  }
  bool empty()
  {
    return _task_queue.empty();
  }

  void push(T task)
  {
    this->Lock();
    _task_queue.push(task);
    this->UnLock();
    this->ComWakeUp();
  }
  void pop(T* task)
  {
    *task = _task_queue.front();
    _task_queue.pop();
  }

  static void* Routine(void* arg)
  {
    pthread_detach(pthread_self()); 
    ThreadPool<T>* tp = static_cast<ThreadPool<T>*>(arg);

    while(1)
    {
      tp->Lock();
      while(tp->empty())
      {
        tp->ComWait();
      }
      //有任务了
      T task;
      tp->pop(&task);
      tp->UnLock();
      task();
    }
  }
  void InitThreadPool()
  {
    pthread_t tid;
    for(int i = 0;i<thread_num;i++)
    {
      pthread_create(&tid,nullptr,Routine,(void*)this);
    }
  }
private:
  queue<T> _task_queue; 
  pthread_mutex_t mtx;
  pthread_cond_t c_cond;
  int thread_num;
};
